package com.xjt.query.service.impl;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.struts2.ServletActionContext;

import com.xjt.cache.LoginCache;
import com.xjt.cache.LoginUuidCache;
import com.xjt.common.CookieKey;
import com.xjt.common.CookieUtils;
import com.xjt.common.IpUtils;
import com.xjt.common.ShowCookieUtils;
import com.xjt.common.StringUtils;
import com.xjt.query.dao.interf.LoginLogDao;
import com.xjt.query.dao.interf.QueryUserDao;
import com.xjt.query.dao.pojo.LoginLog;
import com.xjt.query.dao.pojo.QueryUser;
import com.xjt.query.executor.LoginLogExecutor;
import com.xjt.query.service.interf.LoginService;
import com.xjt.security.Base64;
import com.xjt.security.MD5;

public class LoginServiceImpl implements LoginService {

    // private static final Logger log = Logger.getLogger(LoginAction.class);

    private QueryUserDao queryUserDao;

    private LoginLogDao loginLogDao;

    private LoginUuidCache loginUuidCache;

    protected LoginCache loginCache;

    @Override
    public QueryUser doLogin(String userId, String pwd, String savePwd) {
        return doLogin(userId, pwd, savePwd, null);
    }

    @Override
    public QueryUser doLogin(String userId, String pwd, String savePwd, Map<String, String> errorMap) {
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(pwd)) {
            return null;
        }
        QueryUser dbUserInfo = queryUserDao.selectUserByUserId(userId);
        String encodePwd = MD5.str2md5(pwd);
        // 临时用户
        // if (dbUserInfo.getUserAuthority() == null ||
        // dbUserInfo.getUserAuthority().intValue() ==
        // USER_AUTHORITY.INTERIM) {
        // encodePwd = Base64.encode(pwd);
        // }
        // // 其他用户
        // else {
        // encodePwd = MD5.str2md5(pwd);
        // }
        if (null == dbUserInfo) {
            if (null != errorMap) {
                errorMap.put("userId", "用户名不存在！");
            }
            return null;
        }
        // 判断密码是否正确
        if (encodePwd.equals(dbUserInfo.getUserPwd())) {
            if (!isUserLogon(dbUserInfo.getId())) {
                writeCookie(dbUserInfo.getId(), userId, pwd, savePwd);
                LoginLog logInfo = new LoginLog();
                logInfo.setUserId(userId);
                logInfo.setLoginTime(new Date());
                logInfo.setIp(IpUtils.getIpAddr(ServletActionContext.getRequest()));
                LoginLogExecutor.execute(loginLogDao, logInfo);
                return dbUserInfo;
            }
            else {
                if (null != errorMap) {
                    errorMap.put("userId", "该用户已登录！（一个帐号只能一个人使用！）");
                }
            }
        }
        else {
            if (null != errorMap) {
                errorMap.put("userPwd", "密码不存在！");
            }
        }
        return null;
    }

    /**
     * 用户是否已登录（且不是当前用户）
     * 
     * @param id 用户ID
     * @return
     */
    private boolean isUserLogon(Long id) {
        boolean result = false;
        String uuidCache = loginUuidCache.get(id);
        String uuidCookie = CookieUtils.getCookieValue(ServletActionContext.getRequest(), CookieKey.LOGIN_UUID);
        if (StringUtils.isNotBlank(uuidCache) && !uuidCache.equals(uuidCookie)) {
            result = true;
        }
        return result;
    }

    @Override
    public void doLogout() {
        String logonKey = CookieUtils.getCookieValue(ServletActionContext.getRequest(), CookieKey.LOGIN_KEY);
        Long id = loginCache.remove(logonKey);
        loginUuidCache.remove(id);
    }

    @Override
    public QueryUser selectUserById(Long id) {
        return queryUserDao.selectUserById(id);
    }

    protected void writeCookie(Long id, String userId, String pwd, String savePwd) {
        String token = RandomStringUtils.randomAlphanumeric(12);
        long timestamp = System.currentTimeMillis();
        String encryedKey = MD5.str2md5(id + token + timestamp);
        String uuid = UUID.randomUUID().toString();
        loginCache.put(encryedKey, id);
        loginUuidCache.put(id, uuid);
        ShowCookieUtils.addCookie(CookieKey.LOGIN_KEY, encryedKey, -1);
        ShowCookieUtils.addCookie(CookieKey.LOGIN_USER_ID, userId, 31536000);
        ShowCookieUtils.addCookie(CookieKey.LOGIN_UUID, uuid, Integer.MAX_VALUE);
        String pwdCookieKey = ShowCookieUtils.getCookiePwdName(userId);
        // 是否记住密码
        if ("1".equals(savePwd)) {
            ShowCookieUtils.addCookie(pwdCookieKey, Base64.encode(pwd.getBytes()), 31536000);
        }
        else {
            ShowCookieUtils.removeCookie(pwdCookieKey);
        }
    }

    /**
     * @param queryUserDao the queryUserDao to set
     */
    public void setQueryUserDao(QueryUserDao queryUserDao) {
        this.queryUserDao = queryUserDao;
    }

    /**
     * @param loginLogDao the loginLogDao to set
     */
    public void setLoginLogDao(LoginLogDao loginLogDao) {
        this.loginLogDao = loginLogDao;
    }

    /**
     * @param loginCache the loginCache to set
     */
    public void setLoginCache(LoginCache loginCache) {
        this.loginCache = loginCache;
    }

    /**
     * @param loginUuidCache the loginUuidCache to set
     */
    public void setLoginUuidCache(LoginUuidCache loginUuidCache) {
        this.loginUuidCache = loginUuidCache;
    }

}
